﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Runtime.Serialization;
using WidgetInterface;

/// <summary>
/// Author: AustralTek 
/// Create date: 2010/05/04
/// http://www.australtek.com
/// Copyright: 2009 - 2010
/// Summary description for SlickGrid
/// </summary>
namespace IndustrialDashboard
{
    [Serializable]
    public class IndustrialSlickGrid : IWidget
    {
        private String strSource = "SlickGrid";
        public int columns { get; set; }        
        public string[,] matrix { get; set; }
        public List<Dictionary<string, object>> metadata { get; set; }
        public string message { get; set; }
        private string MsgLog = "";
        public List<string> dataTypesArray = new List<string>();
        
        public IndustrialSlickGrid()
        {
            //
            //
            //
            Logger.Info(strSource, "Initializing");
        }

        public IndustrialSlickGrid(DataSet ds)
        {
            Logger.Info(strSource, "Initializing");
            this.FillSlickGrid(ds);
        }

        public void FillSlickGrid(DataSet ds)
        {
            try
            {
                if (ds != null)
                {
                    if (ds.Tables.Count > 0)
                    {
                        if ((ds.Tables[0].Columns.Count > 0) && (ds.Tables[0].Rows.Count > 0))
                        {
                            columns = ds.Tables[0].Columns.Count;
                            matrix = toStringMatrix(ds.Tables[0]);
                            if (ds.Tables.Count > 1)
                            {
                                metadata = this.GetNormalizedRows(ds.Tables[1]);
                            }
                            else
                            {
                                metadata = null;
                            }
                        }
                        else
                        {
                            if ((ds.Tables[0].Columns.Count > 0) && (ds.Tables[0].Rows.Count == 0)) //Return columns headers 
                            {
                                columns = ds.Tables[0].Columns.Count;
                                matrix = toStringMatrix(ds.Tables[0]);
                            }
                            else
                            {
                                Logger.Warn(strSource, "The data table has no tables columns or tables rows");
                                throw new UserException("The data table has no tables columns or tables rows");
                            }
                        }
                    }
                    else
                    {
                        Logger.Warn(strSource, "The dbo's data has no data tables");
                        throw new UserException("The dbo's data has no data tables");
                    }
                }
                else
                {
                    Logger.Warn(strSource, "The data set is null");
                    throw new UserException("The data set is null");
                }
            }
            catch (Exception ex)
            {
                Logger.Warn(strSource, "",ex);
                Logger.Error(strSource, "", ex);
                throw new UserException("Exception: "+ ex.Message);
            }
        }

        public string GetMessageLog
        {
            get
            {
                return MsgLog;
            }
        }

        private string[,] toStringMatrix(DataTable dt)
        {
            try
            {
                string myPattern = "&#";
                string myReplace = "&amp#";
                Regex myRegExp = new Regex(myPattern);
                string[,] mat = new string[dt.Rows.Count + 1, dt.Columns.Count];
                int i = 0;
                int j = 0;
                int index = 0;
                foreach (DataColumn dc in dt.Columns){
                    mat[i, j++] = dc.ColumnName.Trim();
                    if(dt.Columns[index].DataType.Name == "Boolean") dataTypesArray.Add("bit");
                    if(dt.Columns[index].DataType.Name == "String") dataTypesArray.Add("nvarchar");
                    if(dt.Columns[index].DataType.Name == "DateTime") dataTypesArray.Add("datetime");
                    if (dt.Columns[index].DataType.Name == "Double") dataTypesArray.Add("float");
                    if (dt.Columns[index].DataType.Name == "Single") dataTypesArray.Add("float");
                    if (dt.Columns[index].DataType.Name == "Decimal") dataTypesArray.Add("float");
                    if (dt.Columns[index].DataType.Name == "Int32") dataTypesArray.Add("int");
                    index++;
                }
                i++;
                foreach (DataRow r in dt.Rows){
                    j = 0;
                    foreach (object item in r.ItemArray){
                        mat[i,j] = myRegExp.Replace(item.ToString().Trim(), myReplace);j++;
                    }
                    i++;
                }
                return mat;
            }
            catch (FormatException fe)
            {
                Logger.Warn(strSource, "The SlickGrid's Matrix has not the correct format", fe);
                Logger.Error(strSource, "The SlickGrid's Matrix has not the correct format", fe);
                throw new UserException("The SlickGrid's Matrix has not the correct format. Error: " + fe.Message);
            }
            catch (Exception ex)
            {
                Logger.Warn(strSource, "The SlickGrid's Matrix has not the correct format", ex);
                Logger.Error(strSource, "The SlickGrid's Matrix has not the correct format", ex);
                throw new Exception("The SlickGrid's Matrix has not the correct format. Error: " + ex.Message);
            }
        }

        private List<Dictionary<string, object>> GetNormalizedRows(DataTable dt)
        {
            String strMethod ="GetNormalizedRows()";
            try
            {
                List<Dictionary<string, object>> rows = new List<Dictionary<string, object>>();
                Array.ForEach(
                    dt.Select(),
                    row =>
                    {
                        Dictionary<string, object> Dictionary = new Dictionary<string, object>();
                        foreach (DataColumn col in dt.Columns)
                            Dictionary.Add(col.ColumnName, row[col]);
                        rows.Add(Dictionary);
                    }
                );
                return rows;
            }
            catch (FormatException fe)
            {
                Logger.Warn(strSource,  "Problems getting normalized rows", fe);
                Logger.Error(strSource,  "Problems getting normalized rows", fe);
                throw new UserException("Problems getting normalized rows. Error: " + fe.Message);
            }
            catch (Exception ex)
            {
                Logger.Warn(strSource,  "Problems getting normalized rows", ex);
                Logger.Error(strSource,  "Problems getting normalized rows", ex);
                throw new Exception("Problems getting normalized rows. Error: " + ex.Message);
            }
        }

        public object GenerateResponse(DataSet ds)
        {
            IndustrialSlickGrid sg = new IndustrialSlickGrid(ds);
            return (Object)sg;
        }

        public object GetExcelChunk(System.IO.Stream document)
        {
            Logger.Warn(strSource, "GetExcelChunk() [NotImplementedException]");
            throw new NotImplementedException();            
        }

        public object GetPDFChunk(System.IO.Stream document)
        {
            Logger.Warn(strSource, "GetPDFChunk() [NotImplementedException]");
            throw new NotImplementedException();            
        }
    }
}